home *** CD-ROM | disk | FTP | other *** search
- ;
- ; Copyright (c) 1988 Commodore-Amiga, Inc.
- ;
- ; Executables based on this information may be used in software
- ; for Commodore Amiga computers. All other rights reserved.
- ;
- ; This information is provided "as is"; no warranties are made.
- ; All use is at your own risk, and no liability or responsibility is assumed.
- ;
- CODE
- NOLIST
- INCLUDE "exec/types.i"
- INCLUDE "graphics/rastport.i"
- INCLUDE "custom.i"
- INCLUDE "globals.i"
- LIST
-
- XREF _LVOOwnBlitter,_LVODisownBlitter
-
- XDEF Draw,Line,Clear
-
-
- ;============================================================================
- ; Draw( rp,x2,y2 )
- ; a0 d0 d1
- ;
- ; Same as line but calls OwnBlitter before calling the line drawing routine.
- ;============================================================================
- Draw move.l a6,-(sp)
- movea.l GfxLib(a5),a6 need to own the blitter
- movem.l d0/d1/a0,-(sp) save line arguments
- jsr _LVOOwnBlitter(a6) get the blitter
- movem.l (sp)+,d0/d1/a0 restore line args
- bsr.s Line draw the line
- jsr _LVODisownBlitter(a6) give blitter back to system
- movea.l (sp)+,a6
- rts
-
- ;============================================================================
- ; NAME
- ; Line ( rp,x2,y2 )
- ; a0 d0 d1
- ;
- ; Draws a line from the current position to x2,y2 in the given RastPort.
- ; Current color, linepat, mask and flags are observed from the rastport info.
- ; The blitter must be owned before calling this routine to draw lines.
- ;============================================================================
- Line movem.l d2-d6/a2-a3,-(sp)
- movea.l rp_BitMap(a0),a1 point to the bitmap struct
- movea.l #_custom,a3 point to custom chips
- move.w d0,d2 get start and end points
- move.w d1,d3
- movem.w rp_cp_x(a0),d0/d1 start positions
- movem.w d2/d3,rp_cp_x(a0) save new start position
-
- moveq.l #$0f,d4 compute ASH3-ASH0
- and.w d0,d4 for preshifting bltadat
- sub.w d0,d2 convert X2 to deltaX
- sub.w d1,d3 convert Y2 to deltaY
- mulu.w bm_BytesPerRow(a1),d1 offset to correct bitmap row
- lsr.w #3,d0 convert X1 to a byte offset
- add.w d0,d1 now d1=offset into bitplanes
-
- ; compute the correct octant code for this line ( SUD,SUL,AUL ) and get the
- ; absolute value of max(deltaX, deltaY) into D2 for use as the line length.
- tst.w d2
- bmi.s 40$ deltaX is negative
-
- ; when deltaX is positive, use the following octant generation decisions
- tst.w d3 if deltaY is positive
- bmi.s 20$
- cmp.w d3,d2 ...then if deltaX > deltaY...
- blt.s 10$
- moveq.l #OCT4,d5 ...octant=4
- bra.s GotOctant
- 10$ moveq.l #OCT0,d5 ...else octant=0...
- exg d2,d3 ...and switch the delta values
- bra.s GotOctant
-
- 20$ neg.w d3 else deltaY = -deltaY...
- cmp.w d3,d2 ...if deltaX > deltaY...
- blt.s 30$
- moveq.l #OCT6,d5 ...octant=6
- bra.s GotOctant
- 30$ moveq.l #OCT1,d5 ...else octant=1...
- exg d2,d3 ...and switch the delta values
- bra.s GotOctant
-
- ; but when deltaX is negative, use these octant generation decisions instead
- 40$ neg.w d2 deltaX = -deltaX
- tst.w d3 if deltaY is positive...
- bmi.s 60$
- cmp.w d3,d2 ...then if deltaX > deltaY
- blt.s 50$
- moveq.l #OCT5,d5 ...octant=5
- bra.s GotOctant
- 50$ moveq.l #OCT2,d5 ...else octant=2...
- exg d2,d3 ...and switch the delta values
- bra.s GotOctant
-
- 60$ neg.w d3 else deltaY = -deltaY
- cmp.w d3,d2 if deltaX > deltaY...
- blt.s 70$
- moveq.l #OCT7,d5 ...octant=7
- bra.s GotOctant
- 70$ moveq.l #OCT3,d5 ...else octant = 6...
- exg d2,d3 ...and switch the delta values
-
- ; gets to here with the octant code in D5 and ABS(MAX(deltaX,deltaY)) in D2
- GotOctant addq.w #1,d2 *** is this right ? ***
- 5$ add.w d3,d3 D3 = 2Y
- move.w d3,d0 calculate initial error term
- sub.w d2,d0 D0=2Y-X
- bpl.s 10$ no need to set SIGN
- ori.w #SIGN,d5 initial term is negative so...
- ; we start one line further up
-
- ; this is a bit tricky, we need the start code in the top 4 bits of d5 and d4
- ; but they are currently in the low 4 bits of d4. Instead of shifting them
- ; all the way up to position, we just rotate them around and or them in.
- 10$ ror.w #4,d4 move start code to top bits
- or.w d4,d5 need shift in both halves...
- ; to shift line pattern too
- ori.w #USEA!USEC!USED,d4 move in codes for DMA channels
-
- ; OK, let's start stuffing registers that won't change between successive blits
- ; so we can speed up the innner loop that draws a line in each bit plane. Make
- ; sure that the blitter is not busy from a previous line draw routine before
- ; we start storing to the registers.
- move.w #BBUSY,d6
- 20$ and.w dmaconr(a3),d6 wait for the blitter to finish
- bne.s 20$ still busy
-
- move.w #SETBIT!BLTPRI,dmacon(a3) give blit high priority
- move.w d3,bltbmod(a3) bltbmod=2Y
- move.w d0,d3
- sub.w d2,d3 compute 2Y-2X
- move.w d3,bltamod(a3) bltamod=2Y-2X
- move.w bm_BytesPerRow(a1),bltcmod(a3)
- move.w bm_BytesPerRow(a1),bltdmod(a3)
- moveq.l #-1,d3 first and last masks = $FFFF
- move.l d3,bltafwm(a3) this stores to both
- move.w rp_LinePtrn(a0),bltbdat(a3) set up line pattern
- asl.w #6,d2 convert line length to bltsize
- addq.w #2,d2 width=2 for all line drawing
- move.w d5,bltcon1(a3) set up bltcon1
-
- ; stash things that need frequent reference during the plane drawing loop
- move.b rp_FgPen(a0),d5 get pen color
- and.b rp_Mask(a0),d5 and observe mask
- clr.w d3
- move.b bm_Depth(a1),d3 get a plane counter
- lea.l bm_Planes(a1),a1 point to array of plane ptrs
- bra.s LoopEntry
-
- ; this is the loop that draws lines in each of the required bitplanes.
- ; Registers are set up as follows:-
- ; D0 = 2Y-X
- ; D1 = Offset in bitplane to first word of the line
- ; D2 = BlitSize to start the blitter with
- ; D3 = plane counter
- ; D4 = bltcon0
- ; D5 = pencolor
- ; A1 = pointer to bitplane pointers
- ; A3 = pointer to custom chips
- ; Notice that during the loop, the blitter can be busy drawing the last line
- ; segment while the CPU is setting up for the next load of stores.
- PlaneLoop movea.l (a1)+,a2 get next bitplane address
- adda.w d1,a2 start address of line
- move.b #$0a,d4 assume erasing (minterm = NAC)
- lsr.w #1,d5 shift next bit into carry
- bcc.s 5$ it's 0 so erase this bit
- move.b #$ca,d4 NAC+AB we are drawing the line
-
- 5$ move.w #BBUSY,d6
- 10$ and.w dmaconr(a3),d6 wait for the blitter to finish
- bne.s 10$ still busy
-
- move.w #$8000,bltadat(a3) put in the line bit
- move.l a2,bltcpth(a3) fill in line start address...
- move.l a2,bltdpth(a3) ...of this line
- move.w d0,bltaptl(a3) 2Y-X, needs reloading each use
- move.w d4,bltcon0(a3) store the minterm and stuff
- move.w d2,bltsize(a3) ZOOOOM! start the line draw
- LoopEntry dbra d3,PlaneLoop and do the next plane
-
- movem.l (sp)+,d2-d6/a2-a3 restore regs
- rts all done
-
- ;============================================================================
- ; Clear( rp )
- ; a0
- ;
- ; Clears ALL bitmap memory in the given rastport. Must call OwnBlitter()
- ; before calling this routine (or nasty things will happen fer sure).
- ; This routine assumes all bitplanes are contiguous in memory!!!!!!!!!!!!
- ;============================================================================
- Clear movea.l #_custom,a1 point to custom chips
- movea.l rp_BitMap(a0),a0 get the bitmap ptr
- moveq.l #0,d0
- moveq.l #0,d1
- move.w bm_Rows(a0),d0 calculate blitsize
- move.b bm_Depth(a0),d1
- mulu.w d1,d0 d0 = #lines to clear
- lsl.l #6,d0 move to correct bits
- move.w bm_BytesPerRow(a0),d1 get width in words
- lsr.w #1,d1
- or.w d1,d0 d0 = bltsize reg
-
- move.w #BBUSY,d1
- 10$ and.w dmaconr(a1),d1 wait for blitter to finish
- bne.s 10$ the last operation
-
- move.w #SETBIT!BLTPRI,dmacon(a1) blitter nasty
- clr.l bltamod(a1) bltamod & bltbmod = 0
- clr.l bltcmod(a1) bltcmod & bltdmod = 0
- clr.w bltcon1(a1) no shift or anything special
- move.w #$01f0,bltcon0(a1) only using destination
- move.l bm_Planes(a0),bltdpth(a1) where we are storing to
- clr.w bltadat(a1) what we are storing (0's)
- move.w d0,bltsize(a1) start the blit
- rts done
-
- END
-